//
//  main.cpp
//  IO流
//
//  Created by 卜绎皓 on 2022/12/27.
//

#include <iostream>
#include <istream>
#include <ostream>
using namespace std;

class Date
{
     friend ostream& operator << (ostream& out, const Date& d);
     friend istream& operator >> (istream& in, Date& d);
public:
     Date(int year = 1, int month = 1, int day = 1)
         :_year(year)
         , _month(month)
         , _day(day)
     {}
     operator bool()
    {
        // 这里是随意写的，假设输入_year为0，则结束
         if (_year == 0)
             return false;
         else
             return true;
    }
private:
     int _year;
     int _month;
     int _day;
};

istream& operator >> (istream& in, Date& d)
{
     in >> d._year >> d._month >> d._day;
     return in;
}
ostream& operator << (ostream& out, const Date& d)
{
     out << d._year << " " << d._month <<" "<< d._day ;
     return out;
}

//// C++ IO流，使用面向对象+运算符重载的方式
//// 能更好的兼容自定义类型，流插入和流提取
//int main()
//{
//     // 自动识别类型的本质--函数重载
//     // 内置类型可以直接使用--因为库里面ostream类型已经实现了
//     int i = 1;
//     double j = 2.2;
//     cout << i << endl;
//     cout << j << endl;
//     // 自定义类型则需要我们自己重载<< 和 >>
//     Date d(2022, 4, 10);
//     cout << d;
//     while (d)
//     {
//         cin >> d;
//         cout << d;
//     }
//     return 0;
//}

// 使用文件IO流用文本及二进制方式演示读写配置文件
struct ServerInfo
{
     char _ip[32]; // ip
     int _port; // 端口
};
struct ConfigManager
{
public:
    ConfigManager(const char* configfile = "liren.config")
        :_configfile(configfile)
    {}
    
    void WriteBin(const ServerInfo& info)
    {
        // 这里注意使用二进制方式打开写
        ofstream ofs(_configfile, ifstream::out | ifstream::binary);
        ofs.write((const char*)&info, sizeof(ServerInfo));
    }
    
    void ReadBin(ServerInfo& info)
    {
        // 这里注意使用二进制方式打开读
        ifstream ifs(_configfile, ifstream::in | ifstream::binary);
        ifs.read((char*)&info, sizeof(ServerInfo));
    }
    
    // C++文件流的优势就是可以对内置类型和自定义类型，都使用
    // 一样的方式，去流插入和流提取数据
    // 当然这里自定义类型Date需要重载>> 和 <<
    // istream& operator >> (istream& in, Date& d)
    // ostream& operator << (ostream& out, const Date& d)
    
    void WriteText(const ServerInfo& info)
    {
        // 这里会发现IO流写整形比C语言那套就简单多了，
        // C 语言得先把整形itoa再写
        ofstream ofs(_configfile);
        ofs << info._ip << endl << info._port << endl;
    }
    
    void ReadText(ServerInfo& info)
    {
        // 这里会发现IO流读整形比C语言那套就简单多了，
        // C 语言得先读字符串，再atoi
        ifstream ifs(_configfile);
        ifs >> info._ip >> info._port;
    }
private:
    string _configfile; // 配置文件
};

int main()
{
     ConfigManager cfgMgr;
     ServerInfo winfo = { "192.0.0.1", 80, { 2022, 4, 10 } };
     ServerInfo rdinfo;
    
     // 二进制读写
     cfgMgr.WriteBin(winfo);
     cfgMgr.ReadBin(rdinfo);
     cout << rdinfo._ip << endl;
     cout << rdinfo._port << endl;
    
     // 文本读写
     cfgMgr.WriteText(winfo);
     cfgMgr.ReadText(rdinfo);
     cout << rdinfo._ip << endl;
     cout << rdinfo._port << endl;
     return 0;
}



